package annTrain;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import aNN.InputTargetPair;

import projectUtils.FileUtil;


public class NumericTrainingSet implements TrainingSet {

	private byte[] imageMemory = null, labelMemory = null;
	private List<Integer> memoryIndexSequence;
	private int sequenceIndex;
	private Random randomGen = new Random();
	
	public void LoadTrainingSet(String relativePath, String labelFile, String imageFile) 
	{
		try {
			// "train-labels.idx1-ubyte"
			// "train-images.idx3-ubyte"
			labelMemory = FileUtil.getBytesFromFile(new File(relativePath + File.separator + labelFile));
			imageMemory = FileUtil.getBytesFromFile(new File(relativePath + File.separator + imageFile));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public void GenerateRandomSequence(int temp) 
	{
		List<Integer> randomList = new LinkedList<Integer>();
		memoryIndexSequence = new ArrayList<Integer>(labelMemory.length - 8);
		for (int i = 8; i < labelMemory.length; i++)
		{
			randomList.add(i);
		}
		while (randomList.isEmpty() == false)
		{
			int randomIndex = randomGen.nextInt(randomList.size());
			memoryIndexSequence.add(randomList.get(randomIndex));
			randomList.remove(randomIndex);
		}
		setSequenceIndex(0);
	}

	
	
	@Override
	public InputTargetPair Next() 
	{
		if (getSequenceIndex() >= memoryIndexSequence.size())
			throw new IndexOutOfBoundsException();
		int i = memoryIndexSequence.get(getSequenceIndex());
		setSequenceIndex(getSequenceIndex() + 1);
		Integer target = (int) labelMemory[i];
		double[] desiredValues = new double[10];
		double[] inputValues = new double[841];
		for (int j = 0; j < 10; j++)
		{
			desiredValues[j] = target == j ? 1 : -1;
		}
		for (int j = 0; j < 28; j++)
		{
			for (int k = 0; k < 28; k++)
			{
				byte pixel = imageMemory[(i - 8) * 28 * 28 + 16 + j * 28 + k];
				Double pixelInput = (double) pixel;
				inputValues[j * 29 + k] = pixelInput;
			}
			inputValues[j * 29 + 28] = 0;
		}
		for (int k = 0; k < 29; k++)
		{
			inputValues[28 * 29 + k] = 0;
		}
		return new InputTargetPair(inputValues, desiredValues);
	}

	@Override
	public boolean HasNext() {
		return getSequenceIndex() < memoryIndexSequence.size();
	}

	public void setSequenceIndex(int sequenceIndex) {
		this.sequenceIndex = sequenceIndex;
	}

	public int getSequenceIndex() {
		return sequenceIndex;
	}


}


